/**@mainpage TSGLIB Documentation
@section About
This library is primarily for the Visual Simulation (VIS) module.  Use in the module's in-course assignment is mandatory.
@section Functionality
TSGLIB enables you to create and display virtual 3D worlds at real-time framerates using a scenegraph structure.  The library is extendable to support your own nodes for animation, simulation, and drawing.  Drawing is performed using the OpenGL graphics library.
@section Author
Tyrone Davison, School of Computing, University of Teesside
@section Date
February 2008
@section Build
This documentation refers to build 1.5.1.0
@section Usage
Create a directory called TSG in your Visual Studio project directory.

Extract the zip file contents to it.

Point the compiler at the header files by adding TSG/include to the search path (Project Properties -> C++ -> General -> Additional Include Directories).

Point the linker at the library files by adding TSG/lib to the search path (Project Properties -> Linker -> General -> Additional Library Directories).

You must include the header files within your source code. There is one root header file for the library "tsg.h"

You must link against the library when building your projects (Project Properties -> Linker -> Input -> Additional Dependencies).

You must link against the appropriate CRT (C Runtime) library (Project Properties -> C++ -> Code Generation -> Runtime Library).

Debug Build   -> Multi-threaded Debug CRT -> tsgCored.lib tsgGLd.lib tsgControllerd.lib tsgMathd.lib

Release Build -> Multi-threaded CRT       -> tsgCore.lib tsgGL.lib tsgController.lib tsgMath.lib
@section Support
Support for using the API is available via the VIS discussion forum hosted on the School's intranet. Also use this forum to report any suspected bugs. 
@section Examples

TSGSample1 is an example Visual Studio solution producing a single cube in default colours.

TSGSample2 is source code to show drawing several objects in different colours.

TSGSample3 is source code showing separator nodes being used for objects.

TSGSample4 is source code showing an example controller in use on a rotation transformation.

TSGSample5 is a binary executable showing a slightly more complex scene.

TSGSample6 is source code showing loading a mesh from a COLLADA file and viewing it with an Inspect user controlled camera.

@section History
@par Changes between 1.5.0100 and 1.4.0100
@par
IndexedMesh class has an additional constructor to read the mesh from a 1.4 COLLADA (DAE) file.
@par
Separator can be told to only isolate transformations (via the constructor) to allow light sources to affect the entire scenegraph.
@par
OutputParameter and OutputArrayParameter classes added.
@par
MouseObserver and KeyboardObserver classes added.
@par
InspectController class added.
@par
NurbsCurve class added.
@par
Active bool parameter added to Group; this parameter can be used to skip all the children of a Group or Separator node.
@par
Group::addChild returns the pointer passed into it; this is to make the code look cleaner when you want to release or use the node immediately.
@par Changes between 1.4.0100 and 1.3.0100
@par
ArrayParameter class added.  This class allows nodes and controllers to have arrays of values as input and output parameters.
@par
The internal workings of Parameter have been modified to match those of ArrayParameter.
@par Changes between 1.3.0100 and 1.2.0100
@par
There have been fundamental changes to the TSG framework but it remains backwards compatible with existing code.  The Parameter and Controller classes have been modified to allow for multiple output parameters.
@par
core::Controller2 class added.  This is a replacement base class for creating controllers which allows multiple output parameters.
@par
core::ApplicationTime2 controller added.  This is a replacement controller for ApplicationTime.  It outputs application time and previous frame time.
@par
tsg::math namespace implemented.  Math helper functions (including bezier and frenet) provided.
@par
gl::TSFMesh node added.  This allows a shape to be defined using a TSF formatted XML file.
@par
gl::Bezier3Curve node added. This allows a composite cubic Bezier curve to be drawn.
@par Changes between 1.2.0100 and 1.1.0300
@par
The CRT linking has been changed from dll to static.  This is to avoid problems with demos in the lecture sessions and you executing your applications on machines without visual studio installed.
@par
Class destructors have been made protected to discourage creating %tsg objects on the stack.  All tsg objects should be created using dynamic memory.
@par
gl::Transformation node added.  This node allows a generic transformation to be defined via a matrix.
@par
Documentation has been provided.
@par Changes between 1.1.0300 and 1.1.0100
@par
Improved GL core support for older laptop hardware.
@par Changes between 1.0.0200 and 1.1.0100
@par
The required OpenGL version has been reduced from 1.5 to 1.3 which means TSG will run on older graphics hardware and drivers.
@par
The Timer controller has been replaced with a simpler ApplicationTime controller.  If you used Timer like functionality you will need to implement it yourself.
@par
Additional constructors have been provided for the basic transformation nodes.
*/
#pragma once
#ifndef __TSGCORE__
#define __TSGCORE__


#define TSG_MAJOR_VERSION  1
#define TSG_MINOR_VERSION  5
#define TSG_MAJOR_BUILD    1
#define TSG_MINOR_BUILD    0

#define TSG_SDK_VERSION (TSG_MAJOR_VERSION << 24 | TSG_MINOR_VERSION << 16 | TSG_MAJOR_BUILD << 8 | TSG_MINOR_BUILD)


#pragma warning ( disable : 4355 )


#include <hash_map>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <cassert>


/** Core namespace for TSGLIB.  You should not add anything to this namespace. */
namespace tsg
{

	using stdext::hash_map;
	using std::map;
	using std::set;
	using std::string;
	using std::vector;


	/** Represents a 2D vector. */
	struct Vector2
	{
		float x; /**< x coordinate. */
		float y; /**< y coordinate. */

		/** Default constructor. */
		Vector2( ) : x(0), y(0) {}
		/** Value constructor. */
		Vector2( float X, float Y ) : x(X), y(Y) {}
	};

	/** Represents a 3D vector. */
	struct Vector3
	{
		float x; /**< x coordinate. */
		float y; /**< y coordinate. */
		float z; /**< z coordinate. */

		/** Default constructor. */
		Vector3( ) : x(0), y(0), z(0) {}
		/** Value constructor. */
		Vector3( float X, float Y, float Z ) : x(X), y(Y), z(Z) {}
	};

	/** Represents a 3D homogeneous vector. */
	struct Vector4
	{
		float x; /**< x coordinate. */
		float y; /**< y coordinate. */
		float z; /**< z coordinate. */
		float w; /**< homogeneous coordinate. */

		/** Default constructor. Assumes w=1. */
		Vector4( ) : x(0), y(0), z(0), w(1) {}
		/** Value constructor.  Defaults w=1. */
		Vector4( float X, float Y, float Z, float W=1 ) : x(X), y(Y), z(Z), w(W) {}
	};

	/** Represents an RGB colour. */
	struct Colour
	{
		float r; /**< Red intensity.  Should be in the range [0,1]. */
		float g; /**< Green intensity. Should be in the range [0,1]. */
		float b; /**< Blue intensity.  Should be in the range [0,1]. */

		/** Default constructor. */
		Colour( ) : r(0), g(0), b(0) {}
		/** Value constructor. */
		Colour( float R, float G, float B ) : r(R), g(G), b(B) {}
	};

	/** Represents a transformation matrix. */
	struct Matrix
	{
		float m00, m01, m02, m03;
		float m10, m11, m12, m13;
		float m20, m21, m22, m23;
		float m30, m31, m32, m33;

		/** Default constructor.  Creates an identity matrix. */
		Matrix() : m00(1), m01(0), m02(0), m03(0), m10(0), m11(1), m12(0), m13(0), m20(0), m21(0), m22(1), m23(0), m30(0), m31(0), m32(0), m33(1) {}
		/** Value constructor. */
		Matrix( float M00, float M01, float M02, float M03, float M10, float M11, float M12, float M13, float M20, float M21, float M22, float M23, float M30, float M31, float M32, float M33) : m00(M00), m01(M01), m02(M02), m03(M03), m10(M10), m11(M11), m12(M12), m13(M13), m20(M20), m21(M21), m22(M22), m23(M23), m30(M30), m31(M31), m32(M32), m33(M33) {}
	};


	/** A reference counted object.  This class acts as a base class for most TSG classes. It includes the reference counting mechanism to delete an object only when it is no longer in use. */
	class Base
	{
	public:
		Base ( );
	protected:
		virtual ~Base() {}
	public:
		/** Increases the reference count.  Call this method when you intend to store a pointer to the object beyond the scope of the current function call. */
		void  addRef ( );
		/** Decreases the reference count.  Call this method when you have finished with an object you created in this function call or when you stop storing a pointer previously used with addRef.  @see addRef() */
		void  unRef  ( );
	private:
		long  _refCount;
	};


	/** An interface for classes that wish to observe changes in Parameter objects. */
	class Observer
	{
	public:
		/** Event method to respond when a Parameter object's value has changed. */
		virtual void  onChange ( ) = 0;
	};


	/** An interface for classes which contain Parameter objects.  @see Parameter @see Controller @see Node */
	class Container : public Base, public Observer
	{
	public:
		/** Event method to respond when a Parameter object's value has changed. */
		virtual void  onChange ( ) = 0;
		/** Event method to respond when a Parameter object is required to provide an updated value. */
		virtual void  onDemand ( ) = 0;
	};


	/** A scenegraph node.  This class is a base class for all scenegraph nodes.  Nodes are reference counted objects and contain Parameters. */
	class Node : public Container
	{
	protected:
		Node( const string& name =string() );
		virtual ~Node();
	public:
		/** Get the node name. */
		const string&  name   ( ) const;
		/** Rename the node. */
		void           rename ( const string& );
		/** Render the node.  This method is called during scenegraph traversal.  You should never call this method directly. */
		void           render ( );
		/** Get the unique id of the node. */
		long           uid    ( ) const;
	protected:
		/** Event method to handle rendering the node.  This method will be invoked during scenegraph traversal. All nodes must implement this method. */
		virtual  void  doRender ( ) = 0;
		/** Event method to handle a contained Parameter changing value.  By default nodes do not handle this event. */
		virtual  void  onChange ( ) {}
		/** Event method to handle a contained Parameter being required to update.  By default nodes do not handle this event. */
		virtual  void  onDemand ( ) {}
	private:
		string  _name;
		long    _uid;
	};


	/** Global database of nodes. */
	class Database
	{
	public:
		/** Find a node by name. @return A pointer to the correct node or null if the node was not found. */
		static  Node*        findNode           ( const string& );
		/** Find a node by unique id. @return A pointer to the correct node or null if the node was not found. */
		static  Node*        findNode           ( long uid );
		/** Get the unique id of a node by its name. @return If the node is not found an invalid id will be returned. */
		static  long         getNodeUid         ( const string& );
		/** Checks if a provided node id is valid. */
		static  bool         isValidUid         ( long uid );
		/** Obtain the null node id. */
		static  long         nullUid            ( );
		/** Register a node in the database.  Registering a node provides it with a unique id.  Node constructors call this method.  You should not call it directly yourself. @return Unique id for the node or null id if the process was unsuccessful. */
		static  long         registerNode       ( Node* );
		/** Shutdown the database.  This method should be called before application termination when TSG will no longer be needed. */
		static  void         terminate          ( );
		/** Unregister a node in the database.  Unregistering a node prevents any find methods locating it.  Node destructors call this method.  You should not call it directly yourself. @return If the unregister process was successfull. */
		static  bool         unregisterNode     ( Node* );
	private:
		static  Database*  instance ( );
	private:
		Database();
		~Database();
	private:
		long   generateUid ( );
	private:
		long                    _nextUid;
		map<long,Node*>         _nodeByUid;
		hash_map<string,long>   _uidByName;
	private:
		static  Database*  _instance;
	};


	template< typename T > class Parameter;
	template< typename T > class ArrayParameter;


	/** An animation source.  This interface must be implemented by any class wishing to be used as a source for parameter values. @see Parameter @deprecated It is no longer necessary to inherit from this interface to create animation sources.  Parameters are now used directly as animation sources; such Parameters are usually driven by an intelligent Container such as Controller.  @see Controller */
	template< typename T >
	class Source
	{
	protected:
		virtual ~Source() {}
	public:
		/** Retrieve an up-to-date value.  Parameters will call this method directly when they are being asked for a value.  You should not call this method directly. @see Parameter */
		virtual const T&       getValue ( ) = 0;
		/** Retrieves the source's output Parameter.  This method is required to backwards support the version 1.0 animation system. The framework calls this method directly; there should be no need for you to call it. */
		virtual Parameter<T>*  getOutputParameter ( ) = 0;
	};


	/** An animatable value. Parameters are used by Nodes and Controllers to define their behaviour. */
	template< typename T >
	class Parameter : public Observer
	{
	public:
		/** Standard constructor. @param parent A pointer to the container (usually a node or controller). @param initialValue The initial (unanimated) value of the parameter. @param output Indicates if this Parameter will be used as a Container's output. */
		Parameter  ( Container* parent, const T& initialValue, bool output =false );
		/** Constructor which assumes parameter is to be used for output. @param parent A pointer to the container (usually a node or controller). */
		Parameter  ( Container* parent );
		~Parameter ( );
	public:
		/** Standard value assignment.  @see setValue() */
		const T&  operator= ( const T& );
		/** Standard value retrival. @see getValue() */
		operator const T& ();
		const Parameter&  operator= ( const Parameter& );
	public:
		/** Animate this value from a source. @param source The source Parameter with which to drive this Parameter. This will usually be an output Parameter of a Controller. */
		void      connectFrom ( Parameter<T>* source );
		/** Animate this value from a source. @deprecated Future developments should use Parameters directly as animation sources. */
		void      connectFrom ( Source<T>* );
		/** Stop animating this value. */
		void      disconnect  ( );
		/** Retrieve an up-to-date value. If the parameter is connected to an animation source the value will be retrieved from there. */
		const T&  getValue    ( );
		/** Indicate whether this parameter should be ignored (if possible) during scenegraph traversal. */
		void      ignore      ( bool );
		/** Determine if this parameter is being animated. */
		bool      isConnected ( ) const;
		/** Determine if this parameter is flagged as ignore. */
		bool      isIgnored   ( ) const;
		/** Set the value. If the parameter is connected to an animation source that connection is broken and the new value is used instead. */
		void      setValue    ( const T& );
	private:
		void      onChange    ( );
	private:
		const T*          _currentValue;
		set< Observer* >  _dependents;
		bool              _dirty;
		bool              _ignore;
		bool              _output;
		Container*        _parent;
		Parameter<T>*     _source;
		T                 _value;

		friend ArrayParameter<T>;
	};

	#include "Parameter.inl"


	/** An animatable array of values. ArrayParameter objects are used by Nodes and Controllers to define their behaviour. */
	template< typename T >
	class ArrayParameter : public Observer
	{
	public:
		/** Standard constructor. @param parent A pointer to the container (usually a node or controller). @param initialSize The initial (unanimated) array size.  @param initialValue The initial (unanimated) value of each array element. @param output Indicates if this Parameter will be used as a Container's output. */
		ArrayParameter  ( Container* parent, unsigned int initialSize, const T& initialValue, bool output =false );
		/** Constructor which assumes parameter is to be used for output. @param parent A pointer to the container (usually a node or controller). */
		ArrayParameter  ( Container* parent );
		~ArrayParameter ( );
	public:
		const ArrayParameter&  operator =( const ArrayParameter& );
	public:
		/** Standard value retrival. @see getElement() */
		const T&  operator []( unsigned int );
	public:
		/** Animate this array from a source array. @param source The source ArrayParameter with which to drive this Parameter. This will usually be an output Parameter of a Controller. */
		void          connectFrom        ( ArrayParameter<T>* source );
		/** Animate an array element from a source. @deprecated Provided for compatibility with existing Controller objects. Future developments should use Parameter objects directly as animation sources from within Controller2 objects. */
		void          connectElementFrom ( unsigned int index, Source<T>* source );
		/** Animate an array element from a source. @param index Must be in the range [0,size). @param source The source Parameter with which to drive this Parameter. This will usually be an output Parameter of a Controller. */
		void          connectElementFrom ( unsigned int index, Parameter<T>* source );
		/** Stop animating the array. */
		void          disconnect         ( );
		/** Stop animating an array element. @param index Must be in the range [0,size). */
		void          disconnectElement  ( unsigned int index );
		/** Retrieve an up-to-date value. If the parameter is connected to an animation source the value will be retrieved from there. @param index Must be in the range [0,size). */
		const T&      getElement         ( unsigned int index );
		/** Indicate whether this parameter should be ignored (if possible) during scenegraph traversal. */
		void          ignore             ( bool );
		/** Determine if the entire array or any element within is being animated. */
		bool          isConnected        ( ) const;
		/** Determine if this parameter is flagged as ignore. */
		bool          isIgnored          ( ) const;
		/** Change the array size. This will invalidate the contents and any established animation sources. */
		void          resize             ( unsigned int size );
		/** Sets an array value. If the parameter is connected to an animation source that connection is broken and the new value is used instead. @param index Must be in the range [0,size).*/
		void          setElement         ( unsigned int index, const T& val );
		/** Sets multiple array values. If the parameter is connected to an animation source that connection is broken and the new value is used instead. @param index The first element to start updating.  Must be in the range [0,size).  @param count The number of elements to update. @param data A pointer to an array of size count. */
		void          setElements        ( unsigned int index, unsigned int count, const T* data );
		/** The number of elements in the array. */
		unsigned int  size               ( ) const;
	private:
		void  onChange ( );
	private:
		const vector<T>*         _currentData;
		vector<T>                _data;
		set< Observer*>          _dependents;
		bool                     _dirty;
		vector< Parameter<T>* >  _elementSource;
		bool                     _ignore;
		bool                     _output;
		Container*               _parent;
		ArrayParameter<T>*       _source;
	};

	#include "ArrayParameter.inl"


	/** An animation controller. This class acts as a base for all TSG controllers.  Controllers are animation sources and Parameter containers.  This allows them to be linked together in chains to define complex animation behaviour. @deprecated Use Controller2 where possible. @see Source @see Container */
	template< typename T >
	class Controller : public Source<T>, public Container
	{
	public:
		Controller ( );
	protected:
		virtual ~Controller() {}
	public:
		Parameter<T>*  getOutputParameter ( );
		/** Retrieve an up-to-date value.  Parameters will call this method directly when they are being asked for a value.  You should not call this method directly. @see Parameter */
		const T&       getValue           ( );
	protected:
		/** Register a dependent for this Controller. */
		void  registerDependent ( Observer* );
		/** Set the controller output.  Call this method to provide the output value for the controller.  This should only be called during the onUpdate event method. */
		void  setValue          ( const T& );
	protected:
		/** Event method to handle recomputing the controller output. All controllers must implement this method. */
		virtual void doUpdate ( ) = 0;
	private:
		void  onChange ( );
		void  onDemand ( );
	private:
		bool            _dirty;
		Parameter<T>    _output;
		set<Observer*>  _outputSet;
	};

	#include "Controller.inl"


	/** An animation controller. This class acts as a base for all TSG controllers.  Controllers are Parameter containers, some of which can be output Parameters thus animation sources.  This allows them to be linked together in chains to define complex animation behaviour. @see Parameter @see Container */
	class Controller2 : public Container
	{
	public:
		Controller2 ( );
	protected:
		virtual ~Controller2() {}
	public:
		/** Register a dependent for this Controller. This must be called from the controller's constructor for each Parameter that will be used for output purposes.  Failure to register output parameters will result in downstream parameters not getting updated. */
		void  registerDependent ( Observer* );
	protected:
		/** Event method to handle recomputing the controller output. All controllers must implement this method. */
		virtual void doUpdate       ( ) = 0;
	private:
		void  onChange ( );
		void  onDemand ( );
	private:
		bool            _dirty;
		set<Observer*>  _outputSet;
	};


	/** An output parameter for a controller. Use this instead of the standard Parameter class. */
	template< typename T >
	class OutputParameter : public Parameter<T>
	{
	public:
		OutputParameter( Controller2* parent ) : Parameter(parent) { parent->registerDependent(this); }
		const T&  operator= ( const T& v ) { setValue(v); return v; }
	};


	/** An output array parameter for a controller. Use this instead of the standard ArrayParameter class. */
	template< typename T >
	class OutputArrayParameter : public ArrayParameter<T>
	{
	public:
		OutputArrayParameter( Controller2* parent ) : ArrayParameter(parent) { parent->registerDependent(this); }
	};

};




#endif
